﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using Nixtla.TimeTracker;

namespace Nixtla
{
    namespace UnitTests
    {
        /// <summary>
        /// Unit tests for the Category class
        /// </summary>
        [TestClass]
        public class CategoryUnitTests
        {
            public CategoryUnitTests()
            {
            }

            private TestContext testContextInstance;

            /// <summary>
            ///Gets or sets the test context which provides
            ///information about and functionality for the current test run.
            ///</summary>
            public TestContext TestContext
            {
                get
                {
                    return testContextInstance;
                }
                set
                {
                    testContextInstance = value;
                }
            }

            #region Additional test attributes
            //
            // You can use the following additional attributes as you write your tests:
            //
            // Use ClassInitialize to run code before running the first test in the class
            // [ClassInitialize()]
            // public static void MyClassInitialize(TestContext testContext) { }
            //
            // Use ClassCleanup to run code after all tests in a class have run
            // [ClassCleanup()]
            // public static void MyClassCleanup() { }
            //
            // Use TestInitialize to run code before running each test 
            // [TestInitialize()]
            // public void MyTestInitialize() { }
            //
            // Use TestCleanup to run code after each test has run
            // [TestCleanup()]
            // public void MyTestCleanup() { }
            //
            #endregion

            [TestMethod]
            public void CreateCategory()
            {
                ICategory category = new Category();
                Assert.IsNotNull(category, "ERROR: Failed to create Category object");
                Assert.AreEqual("New Category", category.Name, "ERROR: Name not stored properly");
            }

            [TestMethod]
            public void CheckCategoryName()
            {
                ICategory category = new Category();
                string expectedName = "Test Category";
                category.Name = expectedName;
                Assert.AreEqual(expectedName, category.Name, "ERROR: Name not stored properly");
            }

            [TestMethod]
            public void NewCategoryName()
            {
                ICategory category = new Category();
                string expectedName = "New Category";
                Assert.AreEqual(expectedName, category.Name, "ERROR: Category not initialized with appropriate name");
            }

            [TestMethod]
            public void NewCategoryParent()
            {
                ICategory category = new Category();
                ICategory parentCategory = category.Parent;
                Assert.IsNull(parentCategory);
            }

            [TestMethod]
            public void SetCategoryParent()
            {
                ICategory category = new Category();
                category.Name = "Child";
                ICategory parent = new Category();
                category.Parent = parent;
                Assert.AreEqual(parent, category.Parent, "ERROR: Parent not set");
            }

            [TestMethod]
            public void EnumerateChildrenNone()
            {
                ICategory category = new Category();
                int count = category.Children.Count();
                Assert.AreEqual(0, count, "ERROR: Found children in new category");
            }

            [TestMethod]
            public void EnumerateChildrenOne()
            {
                ICategory parent = new Category();
                parent.Name = "Parent";
                ICategory firstChild = new Category();
                firstChild.Parent = parent;
                int count = parent.Children.Count();
                Assert.AreEqual(1, count, "ERROR: Did not enumerate expected child");
                foreach (Category child in parent.Children)
                {
                    // We only have one, so this will match
                    Assert.AreEqual(firstChild, child, "ERROR: Expected child not found");
                }
            }

            [TestMethod]
            public void EnumerateChildrenTwo()
            {
                ICategory parent = new Category();
                parent.Name = "Parent";
                ICategory firstChild = new Category();
                firstChild.Parent = parent;
                ICategory secondChild = new Category();
                secondChild.Parent = parent;
                int count = parent.Children.Count();
                Assert.AreEqual(2, count, "ERROR: Did not enumerate expected children");
                bool firstFound = false, secondFound = false;
                foreach (Category child in parent.Children)
                {
                    firstFound = firstFound || (firstChild == child);
                    secondFound = secondFound || (secondChild == child);
                }
                Assert.AreEqual(true, firstFound && secondFound, "ERROR: Did not find expected children");
            }

            [TestMethod]
            public void AddAndRemoveParent()
            {
                ICategory parent = new Category();
                parent.Name = "Parent";
                ICategory firstChild = new Category();
                firstChild.Parent = parent;
                int count = parent.Children.Count();
                Assert.AreEqual(1, count, "ERROR: Did not enumerate expected child");
                firstChild.Parent = null;
                count = parent.Children.Count();
                Assert.AreEqual(0, count, "ERROR: Parent category should have no children");
            }

            [TestMethod]
            public void RootQualifiedName()
            {
                ICategory category = new Category();
                string rootName = "IAmTheRoot";
                category.Name = rootName;
                Assert.AreEqual( "\\" + rootName, category.QualifiedName, "ERROR: Qualified name does not match");
            }

            [TestMethod]
            public void LeafQualifiedName()
            {
                ICategory root = new Category();
                string rootName = "root";
                root.Name = rootName;
                ICategory branch = new Category();
                string branchName = "branch";
                branch.Name = branchName;
                branch.Parent = root;
                ICategory leaf = new Category();
                string leafName = "leaf";
                leaf.Name = leafName;
                leaf.Parent = branch;
                Assert.AreEqual( "\\" + rootName + "\\" + branchName + "\\" + leafName,
                    leaf.QualifiedName,
                    "ERROR: Qualifed name not properly formed");
            }
        }
    }
}
